﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.Xml;

namespace 合并XPS文件
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(App.CmdParameters) == false)
            {
                try
                {
                    var fi = new FileInfo(App.CmdParameters);
                    if (fi.Exists && fi.Extension.ToLower().EndsWith(".xps"))
                    {
                        LoadXpsFromMemory(fi.FullName);
                    }

                    cd1.Width = new GridLength(0, GridUnitType.Star);
                    rd1.Height = new GridLength(0, GridUnitType.Star);
                    rd3.Height = new GridLength(0, GridUnitType.Star);
                    gsHorizontal.Visibility = Visibility.Collapsed;
                    gsVertical.Visibility = Visibility.Collapsed;
                    docView.Margin = new Thickness(0);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    BtnLoadXpsFiles_Click(sender, e);
                }
                return;
            }
            else
            {
                BtnLoadXpsFiles_Click(sender, e);
            }
        }

        private void BtnLoadXpsFiles_Click(object sender, RoutedEventArgs e)
        {
            var pathDir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
            lbxXpsFiles.Items.Clear();

            var files = pathDir.GetFiles("*.xps", SearchOption.TopDirectoryOnly);

            foreach (var file in files)
            {
                if (file.Name.ToLower() == "_MergedXpsFile.xps".ToLower()) continue;
                var newItem = new ListBoxCheckedItem(file);
                newItem.MouseDoubleClick += NewItem_MouseDoubleClick;
                lbxXpsFiles.Items.Add(newItem);
            }
        }

        private void LoadXpsFromMemory(string filePath)
        {
            try
            {
                // 1. 读取XPS文件到内存流
                var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                var memoryStream = new MemoryStream();
                fileStream.CopyTo(memoryStream);
                memoryStream.Seek(0, SeekOrigin.Begin);

                // 2. 创建Package对象
                var package = Package.Open(memoryStream, FileMode.Open, FileAccess.Read); 
                        var uri = new Uri($"memorystream://{filePath}");
                PackageStore.AddPackage(uri, package); // 注册到全局存储

                // 3. 初始化XpsDocument
                using (var xpsDoc = new XpsDocument(
                    package,
                    CompressionOption.NotCompressed,
                    uri.AbsoluteUri))
                {
                    var docSeq = xpsDoc.GetFixedDocumentSequence();
                    docView.Document = docSeq;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"加载失败: {ex.Message}");
            }
        }

        private void NewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            LoadXpsFromMemory((sender as ListBoxCheckedItem).FI.FullName);
        }

        private void BtnMergeXpsFiles_Click(object sender, RoutedEventArgs e)
        {
            if (docView.Document != null)
            {
                docView.Document = null;
            }

            string newFile = "_MergedXpsFile.xps";
            File.Delete(newFile);

            if (tcComment.SelectedIndex != 1)
            {
                tcComment.SelectedIndex = 1;
            }

            MergeXpsFiles(newFile);

            //读取并显示
            XpsDocument xpsnewDocument = new XpsDocument(newFile, FileAccess.Read);
            docView.Document = xpsnewDocument.GetFixedDocumentSequence();

            tbxResult.Text += $"[{DateTime.Now.ToLongTimeString()} ]合并完成！\r\n==========\r\n";
            tbxResult.ScrollToEnd();
            DoEvents();
        }

        private void MergeXpsFiles(string newFile)
        {
            tbxResult.Text = $"[{DateTime.Now.ToLongTimeString()} ]准备合并...\r\n";
            tbxResult.ScrollToEnd();

            FixedDocumentSequence newFds = new FixedDocumentSequence();//创建一个新的文档结构
            for (int i = 0; i < lbxXpsFiles.Items.Count; i++)
            {
                var ci = lbxXpsFiles.Items[i] as ListBoxCheckedItem;
                if (ci == null || ci.IsChecked != true) continue;

                tbxResult.Text += $"[{DateTime.Now.ToLongTimeString()} ]正在处理：" + ci.FI.Name + "\r\n";
                tbxResult.ScrollToEnd();
                DoEvents();

                var newDocRef = XpsMergeTool.AddPage(ci.FI.FullName);
                newFds.References.Add(newDocRef);
            }

            tbxResult.Text += $"----------\r\n[{DateTime.Now.ToLongTimeString()} ]准备保存文件，耗时较长，请耐心等候...\r\n";
            tbxResult.ScrollToEnd();
            DoEvents();

            //DocumentReference newDocRef = XpsMergeTool.AddPage(fristFile);//加入第一个文件
            //newFds.References.Add(newDocRef);

            //newDocRef = XpsMergeTool.AddPage(secoFile);
            //newFds.References.Add(newDocRef);//加入第二个文件

            //xps写入新文件
            var NewXpsDocument = new XpsDocument(newFile, System.IO.FileAccess.ReadWrite);
            var xpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(NewXpsDocument);
            xpsDocumentWriter.Write(newFds);
            NewXpsDocument.Close();

            tbxResult.Text += $"[{DateTime.Now.ToLongTimeString()} ]合并文件存盘完毕！\r\n";
            tbxResult.Text += $"[{DateTime.Now.ToLongTimeString()} ]准备载入合并的文件...\r\n";
            tbxResult.ScrollToEnd();
            DoEvents();
        }

        private void BtnSelectAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in lbxXpsFiles.Items)
            {
                var ci = item as ListBoxCheckedItem;
                if (ci == null) continue;

                ci.IsChecked = true;
            }
        }

        private void BtnUnSelectAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in lbxXpsFiles.Items)
            {
                var ci = item as ListBoxCheckedItem;
                if (ci == null) continue;

                ci.IsChecked = false;
            }
        }

        private void BtnSwitchSelect_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in lbxXpsFiles.Items)
            {
                var ci = item as ListBoxCheckedItem;
                if (ci == null) continue;

                if (ci.IsChecked == true)
                {
                    ci.IsChecked = false;
                }
                else
                    ci.IsChecked = true;
            }
        }

        public void DoEvents()
        {
            DispatcherFrame frame = new DispatcherFrame();
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(delegate (object f)
                {
                    ((DispatcherFrame)f).Continue = false;

                    return null;
                }
                    ), frame);
            Dispatcher.PushFrame(frame);
        }
    }

    public class ListBoxCheckedItem : ListBoxItem
    {
        public ListBoxCheckedItem(FileInfo fi)
        {
            cBox.Content = fi.Name;
            this.Content = cBox;
            this.fi = fi;
        }

        private CheckBox cBox = new CheckBox();

        private FileInfo fi;

        public FileInfo FI { get { return fi; } }

        public bool? IsChecked
        {
            get { return cBox.IsChecked; }
            set { cBox.IsChecked = value; }
        }
    }
}
